from PyQt5.QtCore import Qt, QPoint, QDate, QSize
from PyQt5.QtGui import QMovie, QPixmap, QIcon
from PyQt5.QtWidgets import (
    QApplication, QLabel, QMenu, QSystemTrayIcon, QAction, QWidget, QStyle, QDialog, QVBoxLayout, QSlider, QPushButton,
    QSizePolicy, QMessageBox
)
import json
import sys
import os

from pathlib import Path


class FloatingWidget(QWidget):
    def __init__(self, json_file, default_image):
        super().__init__()
        self.json_file = json_file
        self.default_image = default_image
        self.dragging = False
        self.drag_start_position = QPoint()

        # 设置窗口无边框和背景透明
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setAttribute(Qt.WA_NativeWindow, True)

        # 显示GIF
        self.label = QLabel(self)
        self.label.setAlignment(Qt.AlignCenter)

        #加载节日图片
        self.load_festival()

        # 保存初始大小（无论是GIF还是静态图片）
        self.original_size = self.size()
        if self.label.movie():  # 如果是GIF
            self.original_movie_size = self.label.movie().frameRect().size()  # 获取GIF的大小
        else:  # 如果是静态图片
            self.original_movie_size = self.label.pixmap().size()  # 获取静态图片的大小

        # self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)  # 禁止用户手动调整大小
        # self.setMinimumSize(50, 50)
        self.setFixedSize(self.original_size)

        # 托盘图标
        self.tray_icon = QSystemTrayIcon()
        self.tray_icon.setIcon(QIcon("festivalicon.png"))
        self.tray_icon.setToolTip("无限宇宙桌面小组件")  # 提示信息
        self.tray_icon_menu = QMenu()
        self.tray_icon.setContextMenu(self.tray_icon_menu)
        self.add_tray_actions()

        self.tray_icon.show()
        self.scale_factor = 1.0

    def load_festival(self):
        """加载JSON文件并显示对应节日的GIF"""
        try:
            with open(self.json_file, 'r', encoding='utf-8') as file:
                festivals = json.load(file)
            today = QDate.currentDate().toString("MM-dd")
            this_year = QDate.currentDate().toString("yyyy")
            print(today,this_year)
            found = False

            # 遍历所有节日
            for festival in festivals:
                #检查是否与年份有关，某些节日是固定月日，不随年份改变
                if festival.get("relative_year", "") == "False":
                    # 确保节日是阳历节日并且包含今天的日期
                    if festival["calendar_type"] == "solar" and today in festival.get("dates", []):
                        image_path = festival.get("gif_path", "")

                        # 如果找到对应的节日并且路径有效，则加载图片
                        if image_path and os.path.exists(image_path):
                            if image_path.endswith(".gif"):  # GIF格式使用QMovie
                                self.show_gif(image_path)
                            else:  # 其他静态格式使用QPixmap
                                self.show_image(image_path)
                            found = True
                            break
                        else:
                            msg_box = QMessageBox(self)
                            msg_box.setIcon(QMessageBox.Warning)  # 设置图标为警告
                            msg_box.setWindowTitle("图片资源缺失")  # 设置窗口标题
                            msg_box.setText(f"找到了节日，但图片文件 {image_path} 缺失，将会显示默认图片。")  # 显示具体的图片路径
                            msg_box.exec()  # 显示消息框
                            self.show_gif(self.default_image)
                            # self.show_missing_image_message(gif_path)  # 如果没有图片资源，弹出提示框
                            found = True
                            break
                # 逐个遍历确保节日是今年的年份
                elif festival.get("year", "") == int(this_year):
                    # 确保节日是阳历节日并且包含今天的日期
                    if festival["calendar_type"] == "solar" and today in festival.get("dates", []):
                        image_path = festival.get("gif_path", "")

                        # 如果找到对应的节日并且路径有效，则加载图片
                        if image_path and os.path.exists(image_path):
                            if image_path.endswith(".gif"):  # GIF格式使用QMovie
                                self.show_gif(image_path)
                            else:  # 其他静态格式使用QPixmap
                                self.show_image(image_path)
                            found = True
                            break
                        else:
                            msg_box = QMessageBox(self)
                            msg_box.setIcon(QMessageBox.Warning)  # 设置图标为警告
                            msg_box.setWindowTitle("图片资源缺失")  # 设置窗口标题
                            msg_box.setText(f"找到了节日，但图片文件 {image_path} 缺失，将会显示默认图片。")  # 显示具体的图片路径
                            msg_box.exec()  # 显示消息框
                            self.show_gif(self.default_image)
                            # self.show_missing_image_message(gif_path)  # 如果没有图片资源，弹出提示框
                            found = True
                            break
            #假如遍历完了所有都没有对应的节日就用默认的图片
            if not found:
                self.show_gif(self.default_image)
        except Exception as e:
            print("加载节日失败:", e)
            self.show_gif(self.default_image)

    def show_image(self, image_path):
        """显示静态图片 (JPG, PNG, BMP等)"""
        pixmap = QPixmap(image_path)
        if not pixmap.isNull():
            self.label.setPixmap(pixmap)
            self.label.resize(pixmap.size())  # 图片自适应标签大小
            self.resize(pixmap.size())
            self.setFixedSize(pixmap.size())
        else:
            QMessageBox.warning(self, "图片加载失败", f"无法加载图片：{image_path}")

    def show_gif(self, gif_path):
        """显示GIF动图"""
        movie = QMovie(gif_path)
        self.label.setMovie(movie)
        movie.start()
        self.resize(movie.frameRect().size())

        # 获取当前GIF的尺寸
        gif_size = movie.frameRect().size()

        # 更新窗口大小与GIF大小一致
        self.resize(gif_size)
        self.setFixedSize(gif_size)  # 保持固定大小

        # 确保GIF能够适应窗口大小
        self.label.resize(gif_size)
        self.label.movie().setScaledSize(gif_size)

    def add_tray_actions(self):
        """托盘菜单"""
        show_action = QAction("显示", self)
        exit_action = QAction("退出", self)

        show_action.triggered.connect(self.show)
        exit_action.triggered.connect(self.exit_application)

        self.tray_icon_menu.addAction(show_action)
        self.tray_icon_menu.addAction(exit_action)

    def contextMenuEvent(self, event):
        """右键菜单事件"""
        menu = QMenu(self)
        # 设置 QMenu 的样式时，可以通过以下方法去掉底层的黑色背景
        # menu.setWindowFlags( Qt.FramelessWindowHint) # | Qt.NoDropShadowWindowHint
        menu.setAttribute(Qt.WA_TranslucentBackground, True)
        # 设置菜单样式透明背景和圆角
        menu.setStyleSheet("""
            QMenu {
               background-color: rgba(255, 255, 255, 0.8);
                border-radius: 15px;
            }
           QMenu::item{
                padding:10px 20px 10px 20px;
                
            }
            QMenu::item:selected {
                 background-color:rgba(128, 128, 128, 0.3); 
                 padding:10px 20px 10px 20px;
                border-radius: 15px;
                 
            }
            QMenu::separator{
                height: 1px;
                background:rgba(105,105,105,0.5);
                margin:0px 0px 0px 0px;
            }
        """)

        hide_action = QAction("隐藏", self)
        exit_action = QAction("退出", self)
        refresh_action = QAction("刷新", self)
        settings_action = QAction("设置", self)  # 新增的设置选项

        hide_action.triggered.connect(self.hide_to_tray)
        exit_action.triggered.connect(self.exit_application)
        refresh_action.triggered.connect(self.load_festival)
        settings_action.triggered.connect(self.open_settings_dialog)  # 绑定设置窗口

        menu.addAction(hide_action)
        menu.addSeparator()
        menu.addAction(refresh_action)
        menu.addSeparator()
        menu.addAction(settings_action)
        menu.addSeparator()
        menu.addAction(exit_action)

        # 显示菜单
        menu.exec_(event.globalPos())

    def open_settings_dialog(self):
        """打开设置窗口"""

        # 打开对话框前保存当前比例
        self.original_scale_factor = self.scale_factor*1
        self.original_dialog_size = self.size()  # 保存对话框弹出前的原始窗口大小

        self.dialog = SettingsDialog(self)
        self.dialog.slider.setTickPosition(QSlider.TicksAbove)
        self.dialog.slider.setMaximum(300)
        self.dialog.slider.setMinimum(1)

        self.dialog.slider.setValue(int(self.scale_factor * 100))  # 设置当前滑块值为当前比例


        self.dialog.slider.valueChanged.connect(self.on_slider_value_changed)
        # try:
        # 只调用一次exec()，并根据返回的结果来处理
        result = self.dialog.exec()
        if result == QDialog.Accepted:
            new_scale = self.dialog.slider.value() / 100.0
            self.scale_factor = new_scale
            print(self.scale_factor)
            self.adjust_size()
            print("用户点击了确定")

        elif result == QDialog.Rejected:
            self.scale_factor = self.original_scale_factor  # 恢复之前的比例
            self.resize(self.original_dialog_size)  # 恢复原始窗口大小

            print(self.scale_factor)
            print("用户点击了取消")
            self.adjust_size()  # 调整大小



    def adjust_size(self):
        """根据当前比例调整窗口大小"""

        print(f"self.scale_factor+{self.scale_factor}")

        # new_size = self.original_movie_size * self.scale_factor
        new_size=QSize(int(self.original_movie_size.width() * self.scale_factor),int(self.original_movie_size.height() * self.scale_factor))
        new_size_str = f"{new_size.width()}x{new_size.height()}"

        print(f"adjust:{new_size_str} self.scale_factor+{self.scale_factor}")

        # 调整窗口大小以适应 QLabel
        self.resize(new_size)
        # 禁用调整大小
        self.setFixedSize(new_size)

        # 判断是否是 GIF 动画
        if self.label.movie():  # 如果是 GIF 动画
            self.label.movie().setScaledSize(new_size)  # 调整 GIF 动画大小
            self.label.resize(new_size)


        elif self.label.pixmap():
            pixmap = self.label.pixmap()  # 获取当前显示的图片
            if not pixmap.isNull():
                # 使用 QImage 进行平滑缩放
                image = pixmap.toImage()  # 将 QPixmap 转换为 QImage
                scaled_image = image.scaled(new_size,Qt.KeepAspectRatio,Qt.SmoothTransformation)  # 使用平滑插值
                scaled_pixmap = QPixmap.fromImage(scaled_image)  # 将 QImage 转换回 QPixmap
                self.label.setPixmap(scaled_pixmap)  # 更新 QLabel 显示缩放后的图片
                self.label.resize(new_size)

    def on_slider_value_changed(self, value):
        """响应滑块值变化"""
        scale_factor = value / 100.0  # 将滑块值转换为比例因子
        print(value)
        self.apply_scale_factor(scale_factor)
        print("后面的：" + str(scale_factor))

    def apply_scale_factor(self, factor_percent):
        """根据滑块值调整窗口和GIF大小"""
        # 确保比例在合理范围内
        print("传入的值为：" + str(factor_percent))
        factor2 = max(0.01, min(5.0, factor_percent))  # 限制比例在 0.05 到 2.0 之间

        # 计算新大小
        original_size = self.original_movie_size  # 使用保存的初始大小
        new_width = int(original_size.width() * factor2)
        new_height = int(original_size.height() * factor2)
        new_size = QSize(new_width, new_height)

        # 设置 QLabel 和 QMovie 的大小
        self.label.resize(new_size)
        #根据不同图片格式调整大小
        if self.label.movie():  # 如果是 GIF 动画
            self.label.movie().setScaledSize(new_size)  # 调整 GIF 大小
        else:  # 如果是静态图片
            pixmap = self.label.pixmap()  # 获取当前显示的图片
            if not pixmap.isNull():
                tempimage=pixmap.toImage()
                scaled_img=tempimage.scaled(new_size, Qt.KeepAspectRatio, Qt.FastTransformation)
                scaled_pixmap = QPixmap.fromImage(scaled_img)
                self.label.setPixmap(scaled_pixmap)  # 设置调整后的静态图片

        # 调整窗口大小以适应 QLabel
        self.resize(new_size)
        # 禁用调整大小
        self.setFixedSize(new_size)

        # 更新滑块值同步比例（防止数值偏差）
        slider_value = int(factor2 * 100)
        self.dialog.slider.setValue(slider_value)  # 假设滑块对象名为 slider

        # 禁用调整大小
        # self.setFixedSize(self.size())

    def exit_application(self):
        """退出程序并清理资源"""
        self.tray_icon.hide()  # 隐藏托盘图标
        self.tray_icon.deleteLater()  # 删除托盘图标对象
        QApplication.quit()  # 退出应用

    def hide_to_tray(self):
        """隐藏到托盘"""
        self.hide()

    def mousePressEvent(self, event):
        """鼠标按压拖动前记录坐标"""
        if event.button() == Qt.LeftButton:
            self.dragging = True
            self.drag_start_position = event.globalPos() - self.frameGeometry().topLeft()
            event.accept()

    def mouseMoveEvent(self, event):
        """鼠标移动"""
        if self.dragging:
            self.move(event.globalPos() - self.drag_start_position)
            event.accept()

    def mouseReleaseEvent(self, event):
        """鼠标释放"""
        if event.button() == Qt.LeftButton:
            self.dragging = False
            event.accept()


class SettingsDialog(QDialog):
    """设置窗口"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("设置")
        self.setFixedSize(300, 200)

        self.layout = QVBoxLayout(self)

        # 滑块
        self.slider = QSlider(Qt.Horizontal, self)
        self.slider.setMinimum(50)  # 最小尺寸百分比
        self.slider.setMaximum(200)  # 最大尺寸百分比
        self.slider.setValue(100)  # 默认值
        self.layout.addWidget(self.slider)

        # 按钮
        self.ok_button = QPushButton("确定", self)
        self.cancel_button = QPushButton("取消", self)
        self.ok_button.clicked.connect(self.accept)
        self.cancel_button.clicked.connect(self.reject)

        self.layout.addWidget(self.ok_button)
        self.layout.addWidget(self.cancel_button)


if __name__ == "__main__":
    print("Hello World!")
    os.chdir(Path(__file__).parent.as_posix())

    app = QApplication(sys.argv)
    print("app = QApplication(sys.argv)")
    # 默认图片路径
    default_image_path = "images/default.gif"

    widget = FloatingWidget("festivals.json", default_image_path)
    widget.show()
    sys.exit(app.exec_())
